# apps/control/tests.py
# ============================================================
# 针对 index.html 中出现的 3 条接口设计的零依赖单元测试
#
#   ① GET   /devices/                     —— loadDevices()
#   ② PUT   /devices/<device_id>/         —— toggleStatus() / applyMode()
#   ③ POST  /devices/<device_id>/control/ —— handleSlide() / applyMode()
#
# 这里使用内存字典模拟数据，不依赖真实 models / views。
# ============================================================

from django.urls import path, reverse
from django.test import override_settings
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.test import APITestCase

# ----------------------- 内存假设备 -----------------------
DEVICES = {
    "ac-001": {
        "device_id": "ac-001",
        "device_name": "客厅空调",
        "device_type": "空调",
        "location": "客厅",
        "status": "online",
        "control_value": 24,
    },
    "hum-001": {
        "device_id": "hum-001",
        "device_name": "客厅加湿器",
        "device_type": "加湿器",
        "location": "客厅",
        "status": "online",
        "control_value": 50,
    },
}

# ----------------------- 伪视图实现 -----------------------
class DeviceListView(APIView):
    """① 【GET /devices/】—— index.html loadDevices()"""
    permission_classes = []          # 关闭权限检查
    authentication_classes = []      # 关闭认证

    def get(self, request):
        return Response(list(DEVICES.values()), status=200)


class DeviceDetailView(APIView):
    """② 【PUT /devices/<id>/】—— 前端 toggleStatus / applyMode"""
    permission_classes = []
    authentication_classes = []

    def put(self, request, device_id):
        dev = DEVICES.get(device_id)
        if dev is None:
            return Response({"detail": "Not found"}, status=404)

        status_val = request.data.get("status")
        if status_val not in ("online", "offline"):
            return Response({"message": "Invalid status"}, status=400)

        dev["status"] = status_val
        return Response({"message": "Device updated successfully"}, status=200)


class DeviceControlView(APIView):
    """③ 【POST /devices/<id>/control/】—— handleSlide / applyMode"""
    permission_classes = []
    authentication_classes = []

    def post(self, request, device_id):
        dev = DEVICES.get(device_id)
        if dev is None:
            return Response({"detail": "Not found"}, status=404)

        action = request.data.get("action")
        value = request.data.get("value")

        if action != "set" or value is None:
            return Response({"message": "action & value required"}, status=400)

        dev["control_value"] = value
        return Response({"message": "Command sent successfully"}, status=200)


# ----------------------- 动态 URLConf -----------------------
urlpatterns = [
    path("devices/", DeviceListView.as_view(), name="device-list"),
    path("devices/<str:device_id>/", DeviceDetailView.as_view(), name="device-detail"),
    path("devices/<str:device_id>/control/", DeviceControlView.as_view(), name="device-control"),
]

# ----------------------- TestCase 覆盖 index.html 三接口 -----------------------
@override_settings(ROOT_URLCONF=__name__)
class IndexHTMLDeviceAPITests(APITestCase):
    """
    针对 index.html 设备管理相关接口的单元测试
    """

    # ---------- ① /devices/ ----------
    def test_device_list(self):
        """【index.html → GET /devices/】加载全部设备成功"""
        res = self.client.get(reverse("device-list"))
        self.assertEqual(res.status_code, status.HTTP_200_OK)
        self.assertEqual(len(res.data), len(DEVICES))

    # ---------- ② /devices/<id>/ ----------
    def test_device_update_status_online_to_offline(self):
        """【index.html → PUT /devices/<id>/】在线→离线切换成功"""
        res = self.client.put(
            reverse("device-detail", args=["ac-001"]),
            {"status": "offline"}, format="json",
        )
        self.assertEqual(res.status_code, status.HTTP_200_OK)
        self.assertEqual(res.data["message"], "Device updated successfully")
        self.assertEqual(DEVICES["ac-001"]["status"], "offline")

    def test_device_update_status_invalid_id(self):
        """【index.html → PUT /devices/<id>/】设备不存在 → 404"""
        res = self.client.put(
            reverse("device-detail", args=["nonexistent"]),
            {"status": "online"}, format="json",
        )
        self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)

    # ---------- ③ /devices/<id>/control/ ----------
    def test_device_control_set_value(self):
        """【index.html → POST /devices/<id>/control/】正常下发数值指令"""
        res = self.client.post(
            reverse("device-control", args=["hum-001"]),
            {"action": "set", "value": 55}, format="json",
        )
        self.assertEqual(res.status_code, status.HTTP_200_OK)
        self.assertEqual(res.data["message"], "Command sent successfully")
        self.assertEqual(DEVICES["hum-001"]["control_value"], 55)

    def test_device_control_missing_value(self):
        """【index.html → POST /devices/<id>/control/】缺 value → 400"""
        res = self.client.post(
            reverse("device-control", args=["hum-001"]),
            {"action": "set"}, format="json",
        )
        self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST)
